package com.tender.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tender.condition.BizMsgAssoUserCondition;
import com.tender.constants.MsgCenterConstants;
import com.tender.entity.BizMsgAssoUserEntity;
import com.tender.enums.ErrorTypeEnum;
import com.tender.exceptions.CommonException;
import com.tender.mapper.BizMsgRecordMapper;
import com.tender.service.BizMsgAssoUserService;
import com.tender.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class BizMsgAssoUserServiceImpl extends ServiceImpl<BizMsgRecordMapper, BizMsgAssoUserEntity> implements BizMsgAssoUserService {

    private final BizMsgAssoUserEntity instance = new BizMsgAssoUserEntity(){
        {
            setMsgId(MsgCenterConstants.SPECIAL_MSG_ID);  // 设置一个特别的 msgId
        }
    };

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public List<BizMsgAssoUserEntity> selectList(BizMsgAssoUserCondition param) {
        QueryWrapper<BizMsgAssoUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BizMsgAssoUserEntity::getUserId, param.getUserId())
                // 1->已读 0->未读
                .eq(BizMsgAssoUserEntity::getHasRead, 0);
        List<BizMsgAssoUserEntity> list = this.list(queryWrapper);
        return CollectionUtils.isEmpty(list) ? new ArrayList<>() : list;
    }

    @Override
    public BizMsgAssoUserEntity selectOne(BizMsgAssoUserCondition param) {
        return this.selectOne(param, true);
    }

    @Override
    public BizMsgAssoUserEntity selectOne(BizMsgAssoUserCondition param, boolean cache) {
        Long msgId = param.getMsgId();
        if (null == msgId) {
            throw new CommonException(String.format(ErrorTypeEnum.DATA_NOT_EMPTY.getErrorMsgCn(), "msgId"), ErrorTypeEnum.DATA_NOT_EMPTY.getCode());
        }
        log.info("【业务消息记录】msgId: {}", msgId);
        BizMsgAssoUserEntity one = null;
        String redisKey = null;
        if (cache) {
            redisKey = String.format(MsgCenterConstants.MSG_ASS_USER_ONE_KEY, msgId);
            one = (BizMsgAssoUserEntity)redisUtils.get(redisKey);
            if(null != one) {
                if (MsgCenterConstants.SPECIAL_MSG_ID == (one.getMsgId())) {
                    return null;
                }
                return one;
            }
        }

        // 缓存中没有，则查 db
        QueryWrapper<BizMsgAssoUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(BizMsgAssoUserEntity::getMsgId, param.getMsgId())
        ;
        one = this.getOne(queryWrapper);

        if (cache) {
            if (null != one) {
                redisUtils.set(redisKey, one, 5 * 60);
            } else {
                // 防止缓存穿透，设置一个特别 msgId 的对象
                redisUtils.set(redisKey, instance, 5 * 60);
            }
        }

        return one;
    }

    @Override
    public boolean updateByCondition(BizMsgAssoUserCondition param) {
        Long msgId = param.getMsgId();
        Long userId = param.getUserId();
        if (null == msgId) {
            throw new CommonException(String.format(ErrorTypeEnum.DATA_NOT_EMPTY.getErrorMsgCn(), "msgId"), ErrorTypeEnum.DATA_NOT_EMPTY.getCode());
        }
        if (null == userId) {
            throw new CommonException(String.format(ErrorTypeEnum.DATA_NOT_EMPTY.getErrorMsgCn(), "用户id"), ErrorTypeEnum.DATA_NOT_EMPTY.getCode());
        }

        UpdateWrapper<BizMsgAssoUserEntity> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                // 更新条件
                .eq(BizMsgAssoUserEntity::getMsgId, msgId)
                // 要更新的字段
                .set(BizMsgAssoUserEntity::getUpdateUserId, userId)
                .set(null != param.getHasRead(), BizMsgAssoUserEntity::getHasRead, param.getHasRead())
                .set(BizMsgAssoUserEntity::getGmtUpdate, new Date());

        // return this.update(null, updateWrapper); 两者等价
        return this.update(updateWrapper);
    }
}
